/*
 *  BornAgents.cpp
 *  Milovo05-01
 *
 *  Created by Luca Ansaloni on 18/11/07.
 *  Copyright 2007 __MyCompanyName__. All rights reserved.
 *
 */

#include "MilovoTables.h"
#include "MiloInnovation.h"

bool InheritAgentStyle(Mil_Int tmpIDAgentCreated, Agents *tmpCurrentTabAgents, MilovoRandom &tmpCurrentMilovoRandom, 
							  MilovoEnvironment &tmpCurrentMiloEnv);

Agents::iterator GetRandomAgentIter(Agents *tmp_CurrentTabAgents, Mil_Int tmpIDAgentToExclude, MilovoRandom &tmp_CurrentMilovoRandom, 
												MilovoEnvironment &tmp_CurrentMiloEnv);

void CreateInitRecipe(MilinitParams &, SystemParams &, Agents *, Mil_Int , Recipes *, Artifacts *, MilovoRandom &, MilovoEnvironment &);
bool CreateInitRecipeForNewAgent(MilinitParams &, SystemParams &, Mil_Int , Agents *, Mil_Int , Recipes *, Artifacts *, 
											MilovoRandom &, MilovoEnvironment &);

vector<Mil_Int> ExtractVectIDArtifactsKnowedByIDAgentClone(Mil_Int , Mil_Int , Agents *, Artifacts *, Mil_Int);
bool AddThisAgentToKnowledgeOtherAgents(Mil_Int tmpCurrentIDAgentToCreate, Mil_Int tmp_IDAgentToClone, Agents *tmp_TabAgents, Mil_Int tmpDebugLevel);
Mil_Int GetIDAgentToClone(Agents *tmp_TabAgents, MilovoRandom &tmp_MiloRand, MilovoEnvironment &tmp_MiloEnv);

bool CreateNewAgent(Agents *tmpTabAgents, Recipes *tmpTabRecipes, Artifacts *tmpTabArtifacts, Requests *tmpTabRequests, 
						  MilovoRandom &tmpMiloRand, MilinitParams &tmpInitParam, SystemParams &tmpMilovoParam, MilovoEnvironment &tmpMiloEnv)
{
	Mil_Int tmpIDAgentToClone = GetIDAgentToClone(tmpTabAgents, tmpMiloRand, tmpMiloEnv);
	if(tmpIDAgentToClone == 0)
		return false;
	
	Agents::iterator tmpTabAgentsIter = tmpTabAgents->end();
	tmpTabAgentsIter--;
	Mil_Int CurrentIDAgentToCreate = tmpTabAgentsIter->second.GetID() + 1;
	if(tmpMiloEnv.GetDebugLevel() >= 2)
		cout << "NewIDagent: " << CurrentIDAgentToCreate << endl;
	// insert in TabAgents the new agent
	tmpTabAgents->insert(make_pair(CurrentIDAgentToCreate, Agent(CurrentIDAgentToCreate, tmpInitParam.GetStartActivityAgents(), tmpMiloEnv.GetCurrentStep())));
	if((tmpMiloEnv.GetDebugLevel() > 0) && (tmpTabAgents->find(CurrentIDAgentToCreate) == tmpTabAgents->end()))
		exit(EXIT_FAILURE);
	InheritAgentStyle(CurrentIDAgentToCreate, tmpTabAgents, tmpMiloRand, tmpMiloEnv);
	// create recipes of this new agent
	Mil_Int HowManyRecipesThisAgent = tmpMiloRand.GetIntRandom(tmpInitParam.GetNumMinRecipesPerAgent(), tmpInitParam.GetNumMaxRecipesPerAgent());
	for(Mil_Int CurrentIDRecipeToCreate = 0; CurrentIDRecipeToCreate < HowManyRecipesThisAgent; CurrentIDRecipeToCreate++)
		CreateInitRecipeForNewAgent(tmpInitParam, tmpMilovoParam, tmpIDAgentToClone, tmpTabAgents, CurrentIDAgentToCreate, 
											 tmpTabRecipes, tmpTabArtifacts, tmpMiloRand, tmpMiloEnv);
	
	GenerateRelationshipThisAgent(CurrentIDAgentToCreate, tmpTabAgents, tmpTabRecipes, tmpTabArtifacts, tmpMiloEnv.GetCurrentStep(), 
											tmpMiloEnv.GetDebugLevel());
	
	for(Mil_Int NumNewRecipes = 0; NumNewRecipes < HowManyRecipesThisAgent; NumNewRecipes++)
	{
		vector<Mil_Int> VectIDAgents;
		VectIDAgents.push_back(CurrentIDAgentToCreate);
		Agents::iterator tmpTabAgentsIter = tmpTabAgents->find(CurrentIDAgentToCreate);
		if((tmpMiloEnv.GetDebugLevel() >= 0) && (tmpTabAgentsIter == tmpTabAgents->end()))
		{
			cout << "Error in CreateNewAgent function: cannot find tmpTabAgentsIter in tmpTabAgents " << CurrentIDAgentToCreate << endl;
			exit(EXIT_FAILURE);
		}
		tmpTabAgentsIter->second.SetGoal(SelectGoalThisAgent(VectIDAgents, tmpTabAgents, tmpTabRecipes, tmpTabArtifacts, 
																				tmpTabRequests, tmpMiloRand, tmpMiloEnv));
		if(InnovationWithGoal(tmpTabAgentsIter->second.GetGoal(), tmpInitParam, tmpMilovoParam, VectIDAgents, tmpTabAgents, tmpTabRecipes, 
									 tmpTabArtifacts, tmpMiloRand, tmpMiloEnv) == true)
		{
			list<Mil_Int>::iterator LinkRecipesIter = tmpTabAgentsIter->second.LinkRecipes.begin();
			Mil_Int tmpIDRecipeToKill = *LinkRecipesIter;
			KillThisRecipe(tmpIDRecipeToKill, tmpTabRecipes, tmpTabArtifacts, tmpTabAgents, tmpMiloEnv.GetDebugLevel());
		}
	}
	
	AddThisAgentToKnowledgeOtherAgents(CurrentIDAgentToCreate, tmpIDAgentToClone, tmpTabAgents, tmpMiloEnv.GetDebugLevel());
	tmpMiloEnv.SetNumAgentsBorn(tmpMiloEnv.GetNumAgentsBorn() + 1);
	
	return true;
}

bool InheritAgentStyle(Mil_Int tmpIDAgentCreated, Agents *tmpCurrentTabAgents, MilovoRandom &tmpCurrentMilovoRandom, 
							  MilovoEnvironment &tmpCurrentMiloEnv)
{
	Agents::iterator AgentCreatedIter = tmpCurrentTabAgents->find(tmpIDAgentCreated);
	if((tmpCurrentMiloEnv.GetDebugLevel() >= 0) && (AgentCreatedIter == tmpCurrentTabAgents->end()))
	{
		cout << "Error in InheritAgentStyle function: cannot find AgentCreatedIter in tmpCurrentTabAgents: " << tmpIDAgentCreated << endl;
		exit(EXIT_FAILURE);
	}
	Agents::iterator IDAgentForInheritStyleIter;
	// Inherit from IDAgentForInheritStyle to AgentCreatedIter
	AgentCreatedIter->second.Style.SetProbImitation(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																							 tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetProbImitation());
	
	AgentCreatedIter->second.Style.SetProbJump(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																					  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetProbJump());
	
	AgentCreatedIter->second.Style.SetStartJumpRange(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																							  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetStartJumpRange());
	
	AgentCreatedIter->second.Style.SetEndJumpRange(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																							tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetEndJumpRange());
	
	AgentCreatedIter->second.Style.SetSelectGoalInAgentOutput(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																										  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetSelectGoalInAgentOutput());
	
	AgentCreatedIter->second.Style.SetProbGoalFromRequest(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																			 tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetProbGoalFromRequest());
	
	AgentCreatedIter->second.Style.SetProbDevelopNewGoal(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																									tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetProbDevelopNewGoal());
	
	AgentCreatedIter->second.Style.SetHowManyNewFriends(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																								  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetHowManyNewFriends());
	
	AgentCreatedIter->second.Style.SetIncludeZeroAgentInNewFriends(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																												 tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetIncludeZeroAgentInNewFriends());
	
	AgentCreatedIter->second.Style.SetInnovationStrategy(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																									tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetInnovationStrategy());
	
	AgentCreatedIter->second.Style.SetSelectPartnerMode(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																								  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetSelectPartnerMode());
	
	AgentCreatedIter->second.Style.SetValidateRecipeOutput(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																									  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetValidateRecipeOutput());
	
	AgentCreatedIter->second.Style.SetNProduceFloor(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																							 tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetNProduceFloor());
	
	AgentCreatedIter->second.Style.SetNProduceCeil(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																							tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetNProduceCeil());	
	
	AgentCreatedIter->second.Style.SetMaxRecipesAllowed(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																								  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetMaxRecipesAllowed());
	
	AgentCreatedIter->second.Style.SetUseSuppliersChange(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																									tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetUseSuppliersChange());
	
	AgentCreatedIter->second.Style.SetAlfaTransactions(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																								 tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetAlfaTransactions());
	
	AgentCreatedIter->second.Style.SetBetaProjects(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																							tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetBetaProjects());
	
	AgentCreatedIter->second.Style.SetLambdaTransactions(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																									tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetLambdaTransactions());
	
	AgentCreatedIter->second.Style.SetLambdaProjects(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																							  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetLambdaProjects());
	
	AgentCreatedIter->second.Style.SetValueSuccessedProjects(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																										 tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetValueSuccessedProjects());
	
	AgentCreatedIter->second.Style.SetValueFailedProjects(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																									 tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetValueFailedProjects());
	
	AgentCreatedIter->second.Style.SetProjectsDeadLevel(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																								  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetProjectsDeadLevel());
	
	AgentCreatedIter->second.Style.SetScaffProb(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																						tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetScaffProb());
	
	AgentCreatedIter->second.Style.SetAcceptScaffMinLevel(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																									 tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetAcceptScaffMinLevel());
	
	AgentCreatedIter->second.Style.SetUseDeepSearchGoal(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																								  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetUseDeepSearchGoal());

	AgentCreatedIter->second.Style.SetKnowledgeDecay(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																								  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetKnowledgeDecay());
	
	AgentCreatedIter->second.Style.SetChangeSupplierMethod(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																							  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetChangeSupplierMethod());

	AgentCreatedIter->second.Style.SetProduceRecipeMethod(GetRandomAgentIter(tmpCurrentTabAgents, tmpIDAgentCreated, 
																									  tmpCurrentMilovoRandom, tmpCurrentMiloEnv)->second.Style.GetProduceRecipeMethod());	
	
	return true;
}

Agents::iterator GetRandomAgentIter(Agents *tmp_CurrentTabAgents, Mil_Int tmpIDAgentToExclude, MilovoRandom &tmp_CurrentMilovoRandom, 
												MilovoEnvironment &tmp_CurrentMiloEnv)
{
	vector<Mil_Int> VectAgentsAlive;
	GetAgentsAlive(VectAgentsAlive, tmp_CurrentTabAgents, tmp_CurrentMiloEnv.GetDebugLevel());
	
	Mil_Int RandomIDAgent = tmpIDAgentToExclude;
	while(RandomIDAgent == tmpIDAgentToExclude)
		RandomIDAgent = VectAgentsAlive[tmp_CurrentMilovoRandom.GetIntRandom(0, (VectAgentsAlive.size() - 1))];
	
	Agents::iterator RandomIDAgentIter = tmp_CurrentTabAgents->find(RandomIDAgent);
	if((tmp_CurrentMiloEnv.GetDebugLevel() >= 0) && (RandomIDAgentIter == tmp_CurrentTabAgents->end()))
	{
		cout << "Error in GetRandomAgentIter function: cannot find RandomIDAgentIter in tmp_CurrentTabAgents: " << RandomIDAgent << endl;
		exit(EXIT_FAILURE);
	}
	
	return(RandomIDAgentIter);
}

bool CreateInitRecipeForNewAgent(MilinitParams &tmp_InitParam, SystemParams &tmp_MilovoParam, Mil_Int tmp_IDAgentToClone, 
											Agents *tmp_TabAgents, Mil_Int tmpCurrentIDAgentToCreate, Recipes *tmp_TabRecipes, 
											Artifacts *tmp_TabArtifacts, MilovoRandom &tmp_MiloRand, MilovoEnvironment &tmp_MiloEnv)
{
	Agents::iterator tmp_TabAgentsIter = tmp_TabAgents->find(tmpCurrentIDAgentToCreate);
	if((tmp_MiloEnv.GetDebugLevel() >= 0) && (tmp_TabAgentsIter == tmp_TabAgents->end()))
	{
		cout << "Error sending parameters in CreateInitRecipe function: Agent doesn't exist" << endl;
		exit(EXIT_FAILURE);
	}
	vector<Mil_Int> VectIDArtifactsAvailable = ExtractVectIDArtifactsKnowedByIDAgentClone(tmpCurrentIDAgentToCreate, tmp_IDAgentToClone, 
																													  tmp_TabAgents, tmp_TabArtifacts, 
																													  tmp_MiloEnv.GetDebugLevel());
	// follow a cicle for selecting a set of artifacts and operators which output is ok
	bool FlagFoundValidRecipe = false;
	while(FlagFoundValidRecipe == false)
	{
		if(tmp_MiloEnv.GetDebugLevel() >= 1)
			cout << "Try to build a new initialization recipe" << endl;
		list<Mil_Int> tmpListIDInput;
		list<Mil_Int> tmpListOperators;
		// select number of artifacts constituents recipe to create
		Mil_Int tmpHowManyArtifactsThisRecipe = tmp_MiloRand.GetIntRandom(tmp_InitParam.GetNumMinArtifactsPerRecipe(), tmp_InitParam.GetNumMaxArtifactsPerRecipe());
		// insert artifacts in a list manage by recipe
		for(Mil_Int tmpHowManyArtifactsThisRecipeIndex = 0; tmpHowManyArtifactsThisRecipeIndex < tmpHowManyArtifactsThisRecipe; tmpHowManyArtifactsThisRecipeIndex++)
			tmpListIDInput.push_back(VectIDArtifactsAvailable[tmp_MiloRand.GetIntRandom(0, (VectIDArtifactsAvailable.size() - 1))]);
		// insert operators in a list manage by recipe
		Mil_Int tmpHowManyOperatorsThisRecipe = tmpHowManyArtifactsThisRecipe - 1;
		for(Mil_Int tmpHowManyOperatorsThisRecipeIndex = 0; tmpHowManyOperatorsThisRecipeIndex < tmpHowManyOperatorsThisRecipe; tmpHowManyOperatorsThisRecipeIndex++)
			tmpListOperators.push_back(tmp_InitParam.VectOperators[tmp_MiloRand.GetIntRandom(0, tmp_InitParam.VectOperators.size() - 1)]);
		// calculate output of this new recipe
		Mil_Int tmpOutputThisRecipe = CalcOutputThisRecipe(tmpListIDInput, tmpListOperators, tmp_TabArtifacts, tmp_MiloEnv.GetDebugLevel());
		// prepare a vector within the artifacts name that output racipe cannot assume
		vector<Mil_Int> VectToCompareForOutput;
		vector<Mil_Int> VectIDAgentsToAnalize;
		VectIDAgentsToAnalize.push_back(tmpCurrentIDAgentToCreate);
		CheckOutputThisAgentToCompare(VectToCompareForOutput, tmp_InitParam, VectIDAgentsToAnalize, tmp_TabAgents, tmp_TabRecipes, 
												tmp_TabArtifacts, tmp_MiloEnv.GetDebugLevel());
		// Only for Initialization save the type of recipe validation
		Mil_Int SaveValidateRecipeOutputThisAgent = tmp_TabAgentsIter->second.Style.GetValidateRecipeOutput();
		tmp_TabAgentsIter->second.Style.SetValidateRecipeOutput(tmp_InitParam.GetValidateRecipeOutputInitNet());
		// check if output is into boundaries and its name is different to raw materials
		tmpOutputThisRecipe = ValidateThisOutputRecipe(tmp_MilovoParam.GetMinNameArtifactAllowed(), tmp_MilovoParam.GetMaxNameArtifactAllowed(), 
																	  VectToCompareForOutput, tmpOutputThisRecipe, 0, tmp_TabAgents, tmpCurrentIDAgentToCreate, 
																	  tmp_InitParam, tmp_MiloEnv.GetDebugLevel());
		
		tmp_TabAgentsIter->second.Style.SetValidateRecipeOutput(SaveValidateRecipeOutputThisAgent);
		if(tmpOutputThisRecipe != 0)
		{
			FlagFoundValidRecipe = true;
			InsertNewRecipe(tmp_InitParam, tmp_MilovoParam, tmp_MiloRand, tmp_TabAgents, tmpCurrentIDAgentToCreate, tmp_TabRecipes, tmp_TabArtifacts, tmpListIDInput, 
								 tmpListOperators, tmpOutputThisRecipe, tmpHowManyArtifactsThisRecipe, 0, tmp_MiloEnv.GetDebugLevel());
			if(tmp_MiloEnv.GetDebugLevel() >= 1)
				cout << "Initialization of new recipe... ok" << endl << "----------------------------------------" << endl;			
		}
	}
	
	return true;
}

vector<Mil_Int> ExtractVectIDArtifactsKnowedByIDAgentClone(Mil_Int tmp_CurrentIDAgentToCreate, Mil_Int tmp_IDAgentToClone, 
																			  Agents *tmp_TabAgents, Artifacts *tmp_TabArtifacts, Mil_Int CurrentDebugLevel)
{
	//	Aims of this function is to extract into a temporary vector of type Mil_Int, every artifacts (ID of) knowed by current agent
	//	excluded those artifacts produced by itself. This function actually is usefull only for initializate agents network.
	
	vector<Mil_Int> tmpVectIDArtifactsAvailableThisAgent;
	Agents::iterator tmp_IDAgentToCloneIter = tmp_TabAgents->find(tmp_IDAgentToClone);
	if((CurrentDebugLevel >= 0) && (tmp_IDAgentToCloneIter == tmp_TabAgents->end()))
	{
		cout << "Error in ExtractVectIDArtifactsKnowedByIDAgentClone function: cannot find tmp_TabAgentsIter in tmp_TabAgents: " << tmp_IDAgentToClone << endl;
		exit(EXIT_FAILURE);
	}
	
	for(list<Mil_Int>::iterator LinkArtifactsKnowedIter = tmp_IDAgentToCloneIter->second.LinkArtifactsKnowed.begin(); LinkArtifactsKnowedIter != tmp_IDAgentToCloneIter->second.LinkArtifactsKnowed.end(); LinkArtifactsKnowedIter++)
	{
		Artifacts::iterator tmpIDArtifactToAnalizeIter = tmp_TabArtifacts->find(*LinkArtifactsKnowedIter);
		if(tmpIDArtifactToAnalizeIter != tmp_TabArtifacts->end())
			tmpVectIDArtifactsAvailableThisAgent.push_back(tmpIDArtifactToAnalizeIter->second.GetID());
	}
	
	if((CurrentDebugLevel >= 0) && (tmpVectIDArtifactsAvailableThisAgent.size() <= 0))
	{
		cout << "Some error in ExtractVectIDArtifactsKnowedByIDAgentClone function: there aren't ID available (raw materials are included)" << endl;
		cout << "IDAgentClone: " << tmp_IDAgentToClone << endl;
		exit(EXIT_FAILURE);
	}
	
	return(tmpVectIDArtifactsAvailableThisAgent);
}

bool AddThisAgentToKnowledgeOtherAgents(Mil_Int tmpCurrentIDAgentToCreate, Mil_Int tmp_IDAgentToClone, Agents *tmp_TabAgents, Mil_Int tmpDebugLevel)
{
	for(Agents::iterator tmp_TabAgentsIter = tmp_TabAgents->begin(); tmp_TabAgentsIter != tmp_TabAgents->end(); tmp_TabAgentsIter++)
	{
		if(tmp_TabAgentsIter->second.GetID() != tmpCurrentIDAgentToCreate)
		{
			if((tmp_TabAgentsIter->second.TabRelationships.find(tmp_IDAgentToClone) != tmp_TabAgentsIter->second.TabRelationships.end()) && 
				(tmp_TabAgentsIter->second.TabRelationships.find(tmpCurrentIDAgentToCreate) == tmp_TabAgentsIter->second.TabRelationships.end()))
			{
				tmp_TabAgentsIter->second.TabRelationships.insert(make_pair(tmpCurrentIDAgentToCreate, AgentRelationship(tmpCurrentIDAgentToCreate)));
			}
		}
	}
	
	return true;
}

Mil_Int GetIDAgentToClone(Agents *tmp_TabAgents, MilovoRandom &tmp_MiloRand, MilovoEnvironment &tmp_MiloEnv)
{
	Mil_Int tmp_IDAgentToClone = 0;
	vector<Mil_Int> VectIDAgentsAlive;
	
	for(Agents::iterator tmp_TabAgentsIter = tmp_TabAgents->begin(); tmp_TabAgentsIter != tmp_TabAgents->end(); tmp_TabAgentsIter++)
	{
		if((tmp_TabAgentsIter->second.LinkRecipes.size() > 0) && 
			(tmp_TabAgentsIter->second.LinkArtifactsKnowed.size() > 0) && 
			(tmp_TabAgentsIter->second.TabRelationships.size() > 0))
			VectIDAgentsAlive.push_back(tmp_TabAgentsIter->second.GetID());
	}
	
	if(VectIDAgentsAlive.size() > 0)
	{
		tmp_IDAgentToClone = VectIDAgentsAlive[tmp_MiloRand.GetIntRandom(0, (VectIDAgentsAlive.size() - 1))];
		if((tmp_MiloEnv.GetDebugLevel() >= 0) && (tmp_TabAgents->find(tmp_IDAgentToClone) == tmp_TabAgents->end()))
		{
			cout << "Error in GetIDAgentToClone function: tmp_IDAgentToClone not found in tmp_TabAgents: " << tmp_IDAgentToClone << endl;
			exit(EXIT_FAILURE);
		}
	}
	
	return(tmp_IDAgentToClone);
}

